#include "../common/dispacher.hpp"
#include "../client/rpc_client.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "rpc_topic.hpp"

namespace bitpr
{

    namespace server
    {
        // 注册服务端
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port) : _pd_manager(std::make_shared<PDManager>()),
                                       _dispacher(std::make_shared<bitpr::Dispacher>())
            {

                // 设置Dispacher的回调函数
                auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(),
                                            std::placeholders::_1, std::placeholders::_2);
                _dispacher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);

                // 设置server到这个Dispacher的回调函数
                _server = bitpr::ServerFactory::create(port); // 创建服务端
                auto message_cb = std::bind(&bitpr::Dispacher::onMessage, _dispacher.get(),
                                            std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);

                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this,
                                          std::placeholders::_1);
                _server->setCloseCallback(close_cb); // 这个是一个参数的function函数
            }
            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _pd_manager->onConnShutdown(conn);
            }
            PDManager::ptr _pd_manager;
            Dispacher::ptr _dispacher;
            BaseServer::ptr _server;
        };
        class RpcServer
        {

        public:
            using ptr = std::shared_ptr<RpcServer>;
            // 两套地址消息
            // 1.rpc服务提供地址消息--必须是rpc对外访问地址(云服务器---监听地址和访问地址不同)
            // 2.注册中心服务端地址消息--启用服务注册后,链接注册中心进行服务注册
            RpcServer(const Address &access_addr,
                      bool enableRegistry = false,
                      const Address &registry_server_addr = Address()) : _enableRegistry(enableRegistry),
                                                                         _access_addr(access_addr),
                                                                         _router(std::make_shared<bitpr::server::RpcRouter>()),
                                                                         _dispacher(std::make_shared<Dispacher>())
            {
                if (enableRegistry)
                {
                    _reg_client = std::make_shared<client::RegistryClient>(
                        registry_server_addr.first, registry_server_addr.second);
                }
                // 当前成员是一个rpcserver用于rpc服务
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(),
                                        std::placeholders::_1, std::placeholders::_2);
                _dispacher->registerHandler<bitpr::RpcRequest>(bitpr::MType::REQ_RPC, rpc_cb);

                _server = bitpr::ServerFactory::create(access_addr.second);
                auto message_cb = std::bind(&bitpr::Dispacher::onMessage, _dispacher.get(),
                                            std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }
            void registryMethod(const ServiceDescribe::ptr &service)
            {
                if (_enableRegistry)
                {
                    _reg_client->registryMethod(service->method(), _access_addr);
                }
                _router->registerMethod(service);
            }
            void start()
            {
                _server->start();
            }

        private:
            bool _enableRegistry;
            Address _access_addr;
            client::RegistryClient::ptr _reg_client;
            RpcRouter::ptr _router;
            Dispacher::ptr _dispacher;
            BaseServer::ptr _server;
        };
        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port) : _topic_manager(std::make_shared<TopicManager>()),
                                    _dispacher(std::make_shared<bitpr::Dispacher>())
            {
                auto topic_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(),
                                          std::placeholders::_1, std::placeholders::_2);
                _dispacher->registerHandler<TopicRequest>(MType::REQ_TOPIC, topic_cb);

                _server = bitpr::ServerFactory::create(port);
                auto message_cb = std::bind(&bitpr::Dispacher::onMessage, _dispacher.get(),
                                            std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);

                auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }
            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _topic_manager->onShutdown(conn);
            }
            TopicManager::ptr _topic_manager;
            Dispacher::ptr _dispacher;
            BaseServer::ptr _server;
        };
    }
}